////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2010.
// -------------------------------------------------------------------------
//  File name:   LightBox.cpp
//  Version:     v1.00
//  Created:     18/03/2010 by Martin Sherburn.
//  Description: CLightBox implementation.
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "LightBox.h"

//////////////////////////////////////////////////////////////////////////
// CBase implementation.
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CLightBox,CAreaBox)

//////////////////////////////////////////////////////////////////////////
CLightBox::CLightBox()
{
	mv_originAtCorner = true;
	m_entityClass = "LightBox";

	m_box.min=ZERO;
	m_box.max=Vec3(mv_width, mv_length, mv_height);
	mv_disableGI = false;

  m_lightId = GUID_NULL;
	m_pLightBox = NULL;
}

//////////////////////////////////////////////////////////////////////////
void CLightBox::InitVariables()
{
	AddVariable( mv_originAtCorner,"OriginAtCorner",functor(*this, &CLightBox::OnSizeChange) );
	AddVariable( mv_width,"Width",functor(*this,&CLightBox::OnSizeChange) );
	AddVariable( mv_length,"Length",functor(*this,&CLightBox::OnSizeChange) );
	AddVariable( mv_height,"Height",functor(*this,&CLightBox::OnSizeChange) );
	AddVariable( mv_disableGI,"DisableGI",functor(*this, &CLightBox::OnSizeChange) );
}

//////////////////////////////////////////////////////////////////////////
void CLightBox::OnSizeChange(IVariable *pVar)
{
	Vec3 size( mv_width, mv_length, mv_height );
	bool originAtCenter = false;
	mv_originAtCorner.Get(originAtCenter);
	if (originAtCenter)
	{
		m_box.min = ZERO;
		m_box.max = size;
	}
	else
	{
		m_box.min = -size/2;
		m_box.max = size/2;
		// Make volume position bottom of bounding box.
		m_box.min.z = 0;
		m_box.max.z = size.z;
	}
	UpdateGameArea();
}
//////////////////////////////////////////////////////////////////////////
void CLightBox::Serialize( CObjectArchive &ar )
{
	m_bIgnoreGameUpdate = 1;
	CEntityObject::Serialize( ar );
	m_bIgnoreGameUpdate = 0;

	XmlNodeRef xmlNode = ar.node;
	if (ar.bLoading)
	{
		m_entities.clear();

		AABB box;
		xmlNode->getAttr( "BoxMin",box.min );
		xmlNode->getAttr( "BoxMax",box.max );
		SetBox(box);
	}
	else
	{
		// Saving.
		xmlNode->setAttr( "BoxMin",m_box.min );
		xmlNode->setAttr( "BoxMax",m_box.max );
	}
}

//////////////////////////////////////////////////////////////////////////
void CLightBox::UpdateGameArea()
{
	__super::UpdateGameArea();

	// update light box render node parameters directly
	if( m_pLightBox )
	{
		// Update flags
		m_pLightBox->SetLSFlags(mv_disableGI ? ILightShapeRenderNode::elsfDisableGI : 0);
		// Update transform matrix
		Matrix34 wtm = GetWorldTM();
		Vec3 size( mv_width, mv_length, mv_height );
		Vec3 sizeXY( mv_width, mv_length, 0.f );
		Matrix34 mxScale = Matrix34::CreateScale(size);
		if (mv_originAtCorner)
			mxScale.SetTranslation(sizeXY/2);
		wtm = wtm * mxScale;
		Matrix33 rot = Matrix33(wtm);
		rot.Transpose();
		wtm = Matrix34::CreateTranslationMat(Vec3(-.5f, -.5f, 0.f) * rot) * wtm;
		m_pLightBox->SetMatrix(wtm);
	}
}

bool CLightBox::CreateGameObject()
{
	m_pLightBox = static_cast< ILightShapeRenderNode* >( GetIEditor()->Get3DEngine()->CreateRenderNode( eERType_LightShape ) );
	if(m_pLightBox)
		m_pLightBox->LoadLightBox();
	
	return m_pLightBox != NULL && __super::CreateGameObject();
}

void CLightBox::Done()
{
	if( m_pLightBox )
	{
		GetIEditor()->Get3DEngine()->DeleteRenderNode( m_pLightBox );
		m_pLightBox = NULL;
	}

	__super::Done();
}


void CLightBox::StoreUndo( const char *UndoDescription,bool minimal )
{
  CBaseObject::StoreUndo(UndoDescription,minimal);
  UpdateLightBox();
}

//////////////////////////////////////////////////////////////////////////
void CLightBox::UpdateLightBox()
{
  CBaseObject *pObject = FindObject(m_lightId);
  if (pObject && pObject->IsKindOf(RUNTIME_CLASS(CEntityObject)))
  {
    CEntityObject * target = (CEntityObject*)pObject;
    target->Reload();
  }
}

//////////////////////////////////////////////////////////////////////////
void CLightBox::EntityLinked( const CString &name,GUID targetEntityId )
{
  if (targetEntityId != GUID_NULL)
  {
    m_lightId = targetEntityId;
  }
}